﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using WindowsFormsApplication1;
using System.Diagnostics;
using System.IO;
using _2013_ece_csharp_snake;

class ConnexionSendMulti
{
    private Thread listenThread;
    private WindowsFormsApplication1.FormDemo form;
    private EventWaitHandle eventFin;
    private EventWaitHandle eventSend;
    private ConnectionInformation coInf;

    private Socket sendSocket;
    private EndPoint multicastEndPoint;

    public ConnexionSendMulti(WindowsFormsApplication1.FormDemo form, EventWaitHandle eventF, EventWaitHandle eventS, TcpListener tcpListener, ConnectionInformation coInf)
    {
        this.form = form;
        this.eventFin = eventF;
        this.eventSend = eventS;
        this.coInf = coInf;

        createConnexion();

        this.listenThread = new Thread(new ThreadStart(HandleClientComm));
        this.listenThread.IsBackground = true;
        this.listenThread.Start();

        this.listenThread = new Thread(new ThreadStart(askConnection));
        this.listenThread.IsBackground = true;
        this.listenThread.Start();

        this.listenThread = new Thread(new ThreadStart(sendConfirmation));
        this.listenThread.IsBackground = true;
        this.listenThread.Start();

    }

    private void createConnexion()
    {
        sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        multicastEndPoint = new IPEndPoint(IPAddress.Parse("239.1.1.42"), 50000);
    }

    private void HandleClientComm()
    {
        String s;
        int count = 0;

        String ser;
        String ping = "[ping]" + coInf.myName;

        while (!eventFin.WaitOne(100))
        {
            if (this.eventSend.WaitOne(1) && coInf.connected == true)
            {
                s = form.getTextToSend();
                form.receiveMessage("-> Me : " + s);
                s = "[text]" + s;
                sendSocket.SendTo(Encoding.UTF8.GetBytes(s), s.Length, SocketFlags.None, multicastEndPoint);
            }

            if (count > 4 && coInf.connected == true)
            {
                count = 0;

                ser = DataSend.SerializeToString<DataSend>(form.getGameZone().Snake.Data);
                ser = "[data]" + ser;
                sendSocket.SendTo(Encoding.UTF8.GetBytes(ser), ser.Length, SocketFlags.None, multicastEndPoint);

                if (form.getGameZone().Snake.Data.newWall == true)
                    form.getGameZone().Snake.Data.newWall = false;
            }

            // infor that exist
            sendSocket.SendTo(Encoding.UTF8.GetBytes(ping), ping.Length, SocketFlags.None, multicastEndPoint);

            count++;
        }

        // send the close message
        String c = "close";
        sendSocket.SendTo(Encoding.UTF8.GetBytes(c), c.Length, SocketFlags.None, multicastEndPoint);

        sendSocket.Close();
    }

    private void askConnection()
    {
        while (!eventFin.WaitOne(10))
        {
            if (coInf.eventCo.WaitOne(10))
            {
                String s = "[ConnectionDemand]" + coInf.playerIP + "]" + coInf.myName;
                sendSocket.SendTo(Encoding.UTF8.GetBytes(s), s.Length, SocketFlags.None, multicastEndPoint);
            }
        }
    }

    private void sendConfirmation()
    {
        while (!eventFin.WaitOne(10))
        {
            if (coInf.eventConfirmation.WaitOne(10))
            {
                String s = "[ConnectionConfirmation]" + coInf.myIP + "]" + coInf.myName;
                sendSocket.SendTo(Encoding.UTF8.GetBytes(s), s.Length, SocketFlags.None, multicastEndPoint);
            }
        }
    }

    public void close()
    {
        eventFin.Set();
        listenThread.Join();
    }
}
